home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: Franz PD
/
Franz PD Disk #334 (1994-06)(Rhein-Sieg-Soft).zip
/
Franz PD Disk #334 (1994-06)(Rhein-Sieg-Soft).adf
/
ASo-Tools
/
Sources
/
Duplicator.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-01
|
7KB
|
263 lines
/* Duplicator.c
V1.0 - 15.9.92
V1.1 - 1.4.94: kann unter 1.3 fehlerfrei abbrechen
OS2-Utility
Aufruf:
Duplicator <datei> [...] <verzeichnis>
Duplicator kopiert zunächst die genannten Datein ins genannte Verzeichnis.
Danach überwacht er die Dateien mit Notification auf (Schreib-) Zugriffe und
kopiert sie in diesem Falle erneut. Ein gleichzeitiges Umbenennen der
Dateien ist nicht vorgesehen.
Duplicator kann durch ^c / Break <n> C abgebrochen werden.
Die Größe des Kopierpuffers beträgt BUFFSIZE Bytes. Der Puffer wird nur
für solange alloziert gehalten, wie er benutzt wird.
*/
#define BUFFSIZE 32768
#include <exec/memory.h>
#include <exec/ports.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/notify.h>
#include <utility/tagitem.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <stdlib.h>
#include <string.h>
struct ExtNotifyRequest {
struct ExtNotifyRequest *enr_Next;
BOOL enr_NotifyStarted;
struct NotifyRequest enr_NotifyRequest;
};
BPTR OldOut,Out;
struct ExtNotifyRequest *first_enr=NULL;
struct MsgPort *MyPort=NULL;
void CleanUp(void)
{
struct ExtNotifyRequest *tmp_enr;
struct Message *msg;
BPTR myout;
/* Abschied */
Printf("Duplicator endet"); Flush(Output());
if(first_enr)
{
/* die ExtNotifyRequests sukzessiv freigeben */
while(tmp_enr=first_enr)
{
first_enr=first_enr->enr_Next;
if(tmp_enr->enr_NotifyStarted)
EndNotify(&(tmp_enr->enr_NotifyRequest));
FreeVec(tmp_enr);
}
}
/* ggf. den MsgPort freigeben */
if(MyPort) DeleteMsgPort(MyPort);
/* ggf. Ausgabewindow schließen */
if(myout=SelectOutput(OldOut))
{
Delay(150);
Close(Out);
}
}
void Error(char *str, void *arg)
{ /* Fehlerausstieg */
Printf(str,arg);
CleanUp();
exit(RETURN_ERROR);
}
LONG DirEntryType(UBYTE *name)
{ /* ermittelt den fib_DirEntryType zum gegebenen Namen, 0-> Fehler */
BPTR lock;
struct FileInfoBlock *fib;
LONG DET=0;
if(lock=Lock(name,ACCESS_READ))
{
if(fib=AllocDosObjectTags(DOS_FIB,TAG_END))
{
if(Examine(lock,fib)) DET=fib->fib_DirEntryType;
FreeDosObject(DOS_FIB,fib);
}
UnLock(lock);
}
return(DET);
}
#define IsPath(name) (DirEntryType(name)>0)
#define IsFile(name) (DirEntryType(name)<0)
UBYTE *GetENR(UBYTE *name)
{ /* wenn möglich, einen ExtNotifyRequest allozieren, den MessagePort
und Namen eintragen und die Notification starten.
MyPort muß existieren !
Ergebnis: der Eintrag nr_FullName/0 bei Fehler */
struct ExtNotifyRequest *enr;
if(!IsFile(name))
{
Printf("%s ist keine (existente) Datei\n",name);
return(NULL);
}
if(!(enr=(struct ExtNotifyRequest *)
AllocVec(sizeof(struct ExtNotifyRequest),MEMF_CLEAR)))
{
Printf("Duplicator kann den Notify-Request zu %s nicht allozieren\n",name);
return(NULL);
}
enr->enr_Next=first_enr;
first_enr=enr;
enr->enr_NotifyStarted=FALSE;
enr->enr_NotifyRequest.nr_Name=name;
enr->enr_NotifyRequest.nr_stuff.nr_Msg.nr_Port=MyPort;
enr->enr_NotifyRequest.nr_Flags=NRF_SEND_MESSAGE;
enr->enr_NotifyStarted=StartNotify(&(enr->enr_NotifyRequest));
if(!enr->enr_NotifyStarted)
{
Printf("Duplicator kann die Notification von %s nicht beginnen\n",name);
/* Notify-Request freigeben: */
first_enr=enr->enr_Next;
FreeVec(enr);
return(NULL);
}
return(enr->enr_NotifyRequest.nr_FullName);
}
void Copy(UBYTE *from, UBYTE *to)
{ /* Datei des Namens *from nach Pfad *to kopieren */
UBYTE *toname;
VOID *FilePuffer;
int mem_needed;
BPTR FromFile,ToFile;
LONG last_read,copied=0;
Printf("Zu kopieren: %s -> %s\n",from,to);
mem_needed=strlen(from)+strlen(to)+4;
if(toname=(UBYTE *)AllocVec(mem_needed,MEMF_CLEAR))
{
strcpy(toname,to);
if(AddPart(toname,FilePart(from),mem_needed))
{
if(FilePuffer=AllocVec(BUFFSIZE,MEMF_CLEAR))
{
if(FromFile=Open(from,MODE_OLDFILE))
{
if(ToFile=Open(toname,MODE_NEWFILE))
{
do{
last_read=Read(FromFile,FilePuffer,BUFFSIZE);
if(last_read==0) continue;
if(Write(ToFile,FilePuffer,last_read)!=last_read)
{
Printf("Schreibfehler\n");
last_read=0;
}
else copied+=last_read;
} while(last_read);
Printf("%ld Bytes von %s nach %s kopiert\n",copied,from,toname);
Close(ToFile);
}
else Printf("Duplicator kann Zieldatei %s nicht öffnen\n",toname);
Close(FromFile);
}
else Printf("Duplicator kann Quelldatei %s nicht öffnen\n",toname);
FreeVec(FilePuffer);
}
else Printf("Duplicator kann Kopierpuffer nicht allozieren\n");
}
else Printf("Dos will einen zu langen Dateinamen basteln\n");
FreeVec(toname);
}
else Printf("Duplicator kann Namenspuffer nicht allozieren\n");
}
void HandleNotifies(char *todir)
{
register struct NotifyMessage *msg;
while(msg=(struct NotifyMessage *)GetMsg(MyPort))
{
Copy(msg->nm_NReq->nr_FullName,todir);
ReplyMsg((struct Message *)msg);
}
}
extern struct Library *DOSBase;
int main(int argc, char *argv[])
{
int argcnt;
UBYTE *thisname;
LONG GotSigs,ValidSigs;
if(DOSBase->lib_Version<36)
{
Write(Output(),"OS2 required\n",13);
exit(RETURN_FAIL);
}
/* versuchen, ein Window zu öffnen: [wenn's schiefgeht dennoch
weitermachen !] */
OldOut=SelectOutput(Out=
Open("CON:320/11/320/100/Duplicator",MODE_NEWFILE));
if(argc<3)
{
Printf("Aufruf: Duplicator <datei> [...]\n\t\t\t<verzeichnis>\n");
CleanUp();
return(RETURN_WARN);
}
if(!IsPath(argv[argc-1]))
Error("%s ist kein (existenter) Pfad\n",argv[argc-1]);
/* Messageport organisieren */
if(!(MyPort=CreateMsgPort()))
Error("Duplicator kann seinen MsgPort nicht anlegen\n",NULL);
/* die Requests anlegen */
for(argcnt=1;argcnt<argc-1;++argcnt)
if(thisname=GetENR(argv[argcnt]))
{
Copy(thisname,argv[argc-1]);
Printf("Notification von %s hat begonnen\n",thisname);
}
if(first_enr)
{
/* die relevanten Signale ausfiltern */
ValidSigs=(SIGBREAKF_CTRL_C | (1<<MyPort->mp_SigBit));
/* auf Abbruch oder Notify-Message warten */
for(GotSigs=(SetSignal(0,0) & ValidSigs);
(GotSigs & SIGBREAKF_CTRL_C)==0;
GotSigs=Wait(ValidSigs) )
{
HandleNotifies(argv[argc-1]);
if(GotSigs & SIGBREAKF_CTRL_C) continue;
while(GotSigs=(SetSignal(0,0) & ValidSigs))
{
HandleNotifies(argv[argc-1]);
if(GotSigs & SIGBREAKF_CTRL_C) break;
}
}
Printf("^C ... "); Flush(Output());
}
else Printf("Keine der Notifications ist möglich, Sie \23332mRindvieh\23331m !\n");
CleanUp();
return(RETURN_OK);
}